﻿//Project: CassiniWrapper
//Martin CLAVREUIL
//martin@clavreuil.com

using System;
using System.Net;
using System.Net.Sockets;

namespace CassiniWrapper
{
    /// <summary>
    /// Utility class to search for a port number to listen to
    /// Usage: GetNextAvailablePort (automatic at the startup of the main form)
    /// IsAvailable: for internal use or to validate user input
    /// </summary>
    class NetworkPortManager
    {
        const int portIterationMaxLimit = 100;
        /// <summary>
        /// Get the next available port
        /// </summary>
        /// <param name="startPort">Port number to begin to scan from</param>
        /// <returns>An available port number to listen to</returns>
        public int GetNextAvailablePort(int startPort)
        {
            int response = Math.Max(startPort, 1);
            for (int i = startPort; i < startPort+portIterationMaxLimit; i++)
            {
                if (IsAvailable(i))
                {
                    response = i;
                    break;
                }
            }
            if (response < startPort)
            {
                System.Resources.ResourceManager rssmgr = new System.Resources.ResourceManager("CassiniWrapper.Languages.Strings", System.Reflection.Assembly.GetExecutingAssembly());
                throw new Exception(rssmgr.GetString("ERR_NoAvailablePortInRange") + "[" + startPort + ";" + startPort + portIterationMaxLimit + "]");
            }
            return response;
        }
        
        /// <summary>
        /// Checks if the spacified port is currently available
        /// </summary>
        /// <param name="port">Port number to check</param>
        /// <returns>Availability (yes/no)</returns>
        public bool IsAvailable(int port)
        {
            bool response = false;
            TcpListener tempListener;
            try
            {
                tempListener = new TcpListener(IPAddress.Loopback, port);
                tempListener.Start();
                response = true;
                tempListener.Stop();
            }
            catch { }
            finally
            {
                tempListener = null;
            }
            return response;
        }
    }
}
